import 'dart:io';
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../models/map_models.dart';
import '../providers/map_editor_provider.dart';
import 'rect_image.dart';

class MapView extends StatefulWidget {
  const MapView({super.key});

  @override
  State<MapView> createState() => _MapViewState();
}

class _MapViewState extends State<MapView> {
  final TransformationController _transformationController = TransformationController();
  Offset? _panStart;
  
  @override
  void dispose() {
    _transformationController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Consumer<MapEditorProvider>(
      builder: (context, provider, child) {
        if (!provider.hasMap) {
          return Container(
            color: Colors.grey[200],
            child: const Center(
              child: Text(
                '请创建或打开一个地图',
                style: TextStyle(
                  fontSize: 18,
                  color: Colors.grey,
                ),
              ),
            ),
          );
        }

        return Container(
          color: Colors.grey[100],
          child: InteractiveViewer(
            transformationController: _transformationController,
            minScale: 0.1,
            maxScale: 5.0,
            // 允许单指点击绘制，禁用平移手势以避免冲突
            panEnabled: provider.editMode == EditMode.view,
            child: Center(
              child: GestureDetector(
                onTapDown: (details) => _handleTap(details, provider),
                onPanStart: (details) => _panStart = details.localPosition,
                onPanUpdate: (details) => _handlePan(details, provider),
                onPanEnd: (details) => _panStart = null,
                child: CustomPaint(
                  painter: MapPainter(
                    map: provider.currentMap!,
                    provider: provider,
                  ),
                  child: SizedBox(
                    width: provider.currentMap!.width * provider.currentMap!.tileWidth.toDouble() * provider.zoomLevel,
                    height: provider.currentMap!.height * provider.currentMap!.tileHeight.toDouble() * provider.zoomLevel,
                  ),
                ),
              ),
            ),
          ),
        );
      },
    );
  }

  void _handleTap(TapDownDetails details, MapEditorProvider provider) {
    print('Map tap detected! EditMode: ${provider.editMode}, SelectedTileId: ${provider.selectedTileId}');
    
    if (provider.editMode == EditMode.view) {
      print('In view mode, ignoring tap');
      return;
    }

    final map = provider.currentMap!;
    final localPosition = details.localPosition;
    
    // Calculate tile coordinates
    final tileX = (localPosition.dx / (map.tileWidth * provider.zoomLevel)).floor();
    final tileY = (localPosition.dy / (map.tileHeight * provider.zoomLevel)).floor();
    
    print('Calculated tile position: ($tileX, $tileY), Map size: (${map.width}, ${map.height})');
    
    if (tileX >= 0 && tileX < map.width && tileY >= 0 && tileY < map.height) {
      final tileId = provider.editMode == EditMode.delete ? 0 : provider.selectedTileId;
      print('Setting tile at ($tileX, $tileY) with ID: $tileId');
      provider.setTile(tileX, tileY, tileId);
    } else {
      print('Tile position out of bounds');
    }
  }

  void _handlePan(DragUpdateDetails details, MapEditorProvider provider) {
    if (provider.editMode == EditMode.view || _panStart == null) return;

    final map = provider.currentMap!;
    final localPosition = details.localPosition;
    
    // Calculate tile coordinates
    final tileX = (localPosition.dx / (map.tileWidth * provider.zoomLevel)).floor();
    final tileY = (localPosition.dy / (map.tileHeight * provider.zoomLevel)).floor();
    
    if (tileX >= 0 && tileX < map.width && tileY >= 0 && tileY < map.height) {
      final tileId = provider.editMode == EditMode.delete ? 0 : provider.selectedTileId;
      provider.setTile(tileX, tileY, tileId);
    }
  }
}

class MapPainter extends CustomPainter {
  final TileMap map;
  final MapEditorProvider provider;
  
  MapPainter({
    required this.map,
    required this.provider,
  });

  @override
  void paint(Canvas canvas, Size size) {
    final paint = Paint();
    final tileWidth = map.tileWidth.toDouble() * provider.zoomLevel;
    final tileHeight = map.tileHeight.toDouble() * provider.zoomLevel;

    // Draw layers from bottom to top
    for (int layerIndex = 0; layerIndex < map.layers.length; layerIndex++) {
      final layer = map.layers[layerIndex];
      
      if (!layer.visible) continue;

      paint.color = paint.color.withAlpha((layer.opacity * 255).round());
      
      // Draw tiles in this layer
      for (int y = 0; y < layer.height; y++) {
        for (int x = 0; x < layer.width; x++) {
          final tileId = layer.data[y][x];
          if (tileId > 0) {
            _drawTile(canvas, paint, x, y, tileId, tileWidth, tileHeight);
          }
        }
      }
      
      // Highlight current layer with semi-transparent overlay if it's not the active layer
      if (provider.currentLayerIndex != layerIndex && !provider.state.showGrid) {
        paint.color = Colors.white.withAlpha(80);
        canvas.drawRect(
          Rect.fromLTWH(0, 0, size.width, size.height),
          paint,
        );
      }
    }

    // Draw grid if enabled
    if (provider.showGrid) {
      _drawGrid(canvas, size, tileWidth, tileHeight);
    }

    // Draw ruler if enabled
    if (provider.showRuler) {
      _drawRuler(canvas, size, tileWidth, tileHeight);
    }
  }

  void _drawTile(Canvas canvas, Paint paint, int x, int y, int tileId, double tileWidth, double tileHeight) {
    final rect = Rect.fromLTWH(
      x * tileWidth,
      y * tileHeight,
      tileWidth,
      tileHeight,
    );

    if (tileId == 0) return; // 空图块不绘制

    // 查找对应的图块集
    TileSet? tileSet;
    int tileIndex = 0;
    
    for (final ts in map.tileSets) {
      if (tileId >= ts.firstGid && tileId < ts.firstGid + ts.tileCount) {
        print("tileSet = "+ts.toString());
        tileSet = ts;
        tileIndex = tileId - ts.firstGid;
        break;
      }
    }

    if (tileSet != null) {
      // 尝试加载并绘制实际图片
      _drawTileImage(canvas, paint, rect, tileSet, tileIndex);
    }
  }

  void _drawTileImage(Canvas canvas, Paint paint, Rect rect, TileSet tileSet, int tileIndex) {
    final imagePath = tileSet.imagePath;
    print("image path = "+imagePath);
    // 检查图片文件是否存在
    if (!File(imagePath).existsSync()) {
      _drawFallbackTile(canvas, paint, rect, tileIndex);
      return;
    }

    // 尝试从 Provider 的缓存获取图片
    final cachedImage = provider.imageCache[imagePath];
    print("imageCache = "+provider.imageCache.keys.toString());
    if (cachedImage != null) {
      // 计算图块在图片中的位置
      final row = tileIndex ~/ tileSet.columns;
      final col = tileIndex % tileSet.columns;
      final sourceX = col * tileSet.tileWidth.toDouble();
      final sourceY = row * tileSet.tileHeight.toDouble();
      
      final sourceRect = Rect.fromLTWH(
        sourceX,
        sourceY,
        tileSet.tileWidth.toDouble(),
        tileSet.tileHeight.toDouble(),
      );
      
      // 绘制图块
      canvas.drawImageRect(cachedImage, sourceRect, rect, paint);
      
      // 绘制边框
      paint.color = Colors.black26;
      paint.style = PaintingStyle.stroke;
      paint.strokeWidth = 0.5;
      canvas.drawRect(rect, paint);
      paint.style = PaintingStyle.fill;
    } else {
      // 异步加载图片
      provider.loadTileSetImage(imagePath);
      // 在图片加载期间显示占位符
      _drawFallbackTile(canvas, paint, rect, tileIndex);
    }
  }

  void _drawFallbackTile(Canvas canvas, Paint paint, Rect rect, int tileIndex) {
    // 绘制灰色背景
    paint.color = Colors.grey[300]!;
    canvas.drawRect(rect, paint);
    
    // 绘制图块索引
    final fontSize = (rect.width / 4).clamp(8.0, 16.0);
    final textPainter = TextPainter(
      text: TextSpan(
        text: tileIndex.toString(),
        style: TextStyle(
          color: Colors.black87,
          fontSize: fontSize,
          fontWeight: FontWeight.bold,
        ),
      ),
      textDirection: TextDirection.ltr,
    );
    
    textPainter.layout();
    
    final textOffset = Offset(
      rect.left + (rect.width - textPainter.width) / 2,
      rect.top + (rect.height - textPainter.height) / 2,
    );
    
    textPainter.paint(canvas, textOffset);
    
    // 绘制边框
    paint.color = Colors.black54;
    paint.style = PaintingStyle.stroke;
    paint.strokeWidth = 0.5;
    canvas.drawRect(rect, paint);
    paint.style = PaintingStyle.fill;
  }

  void _drawGrid(Canvas canvas, Size size, double tileWidth, double tileHeight) {
    final gridPaint = Paint()
      ..color = Colors.black26
      ..strokeWidth = 0.5;

    // Draw vertical lines
    for (double x = 0; x <= size.width; x += tileWidth) {
      canvas.drawLine(
        Offset(x, 0),
        Offset(x, size.height),
        gridPaint,
      );
    }

    // Draw horizontal lines
    for (double y = 0; y <= size.height; y += tileHeight) {
      canvas.drawLine(
        Offset(0, y),
        Offset(size.width, y),
        gridPaint,
      );
    }
  }

  void _drawRuler(Canvas canvas, Size size, double tileWidth, double tileHeight) {
    final paint = Paint()
      ..color = Colors.black54
      ..style = PaintingStyle.fill;

    final textPainter = TextPainter(
      textDirection: TextDirection.ltr,
    );

    // Draw horizontal ruler numbers
    for (int x = 0; x < map.width; x++) {
      if (x % 5 == 0 || x < 10) {  // Show every 5th number or first 10
        textPainter.text = TextSpan(
          text: x.toString(),
          style: const TextStyle(
            color: Colors.black54,
            fontSize: 10,
          ),
        );
        textPainter.layout();
        textPainter.paint(
          canvas,
          Offset(x * tileWidth + 2, 2),
        );
      }
    }

    // Draw vertical ruler numbers
    for (int y = 0; y < map.height; y++) {
      if (y % 5 == 0 || y < 10) {  // Show every 5th number or first 10
        textPainter.text = TextSpan(
          text: y.toString(),
          style: const TextStyle(
            color: Colors.black54,
            fontSize: 10,
          ),
        );
        textPainter.layout();
        textPainter.paint(
          canvas,
          Offset(2, y * tileHeight + 2),
        );
      }
    }
  }

  @override
  bool shouldRepaint(covariant MapPainter oldDelegate) {
    return oldDelegate.map != map ||
           oldDelegate.provider.state != provider.state;
  }
}